package com.rankeiot.platform.controller;

import cn.hutool.core.lang.Validator;
import com.rankeiot.core.Current;
import com.rankeiot.core.anno.Auth;
import com.rankeiot.core.config.ConfigManager;
import com.rankeiot.core.data.UserInfo;
import com.rankeiot.core.data.response.Resp;
import com.rankeiot.core.util.Captcha;
import com.rankeiot.core.util.RsaUtil;
import com.rankeiot.core.util.StringUtil;
import com.rankeiot.core.util.TokenUtil;
import com.rankeiot.platform.config.PlatformConfig;
import com.rankeiot.platform.config.SmsConfigs;
import com.rankeiot.platform.domain.User;
import com.rankeiot.platform.domain.WxUser;
import com.rankeiot.platform.events.UserRegisterEvent;
import com.rankeiot.platform.service.SmsService;
import com.rankeiot.platform.service.UserService;
import com.rankeiot.platform.service.WxMpService;
import com.rankeiot.platform.util.PasswordUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.sagacity.sqltoy.dao.SqlToyLazyDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Tag(name = "APP接口")
//@Auth
@RestController
@RequestMapping("client")
@RequiredArgsConstructor
public class ClientController {

    final UserService userService;
    final WxMpService wxMpService;
    final SqlToyLazyDao dao;
    final ApplicationContext context;

    private SmsService smsService;
    //app登录
    //时间戳+appName+密码加密
    @Autowired(required = false)
    public void setSmsService(SmsService smsService){
        this.smsService=smsService;
    }

    @Schema(description = "用户登录信息")
    @Data
    public static class LoginVo {
        @Schema(description = "用户名")
        String username;
        @Schema(description = "密码编码，aes(realpassword,md5(t))")
        String password;
        @Schema(description = "登录时间戳")
        long t;
    }

    @Operation(summary = "微信小程序自动登录")
    @PostMapping("mp_auto_login")
    public Resp wxAutoLogin(String code) {
        Map<String, String> resp = wxMpService.userInfo(code);
        String unionId = resp.get("unionid");
        String openId = resp.get("openid");
        WxUser wxUser = new WxUser();
        wxUser.setOpenid(openId);
        wxUser.setUnionId(unionId);
        WxUser sys_wxUser = dao.loadBySql("SELECT * FROM t_user_wx WHERE #[union_id=:unionId] #[OR openid=:openid] ", wxUser);
        User user = null;
        boolean isNew=false;
        if (sys_wxUser == null) {
            if ("true".equals(PlatformConfig.AUTO_REG.strValue())) {
                user = createUser(wxUser);
                isNew=true;
            } else {
                Resp.fail("用户未注册");
            }
        } else {
            user = new User();
            user.setId(sys_wxUser.getUserId());
            user = dao.load(user);
            if (user == null) {
                Resp.fail("没有该微信用户");
            }
        }
        UserInfo userInfo = userService.loadUserInfo(user.getUsername(), null);
        if(userInfo==null){
            Resp.fail("用户不存在或已注销");
        }
        Current.login(userInfo);
        return Resp.map()
                .set("isNew",isNew)
                .set("user", userInfo)
                .set("uk", user.getPassword() + TokenUtil.getGlobalSalt());
    }
    @Operation(summary = "微信小程手机号登录")
    @PostMapping("mp_phone_login")
    public Resp loginByMpPhone(String code){
       String phoneNum= wxMpService.getPhoneNum(code);
       User user=new User();
       user.setUsername(phoneNum);
       user=dao.loadBySql("SELECT * FROM t_user WHERE username=:username",user);
       boolean isNew=false;
       if(user==null){
           if ("true".equals(PlatformConfig.AUTO_REG.strValue())) {
               user = createUser(phoneNum);
               isNew=true;
           } else {
               Resp.fail("用户未注册");
           }
       }
        UserInfo userInfo = userService.loadUserInfo(user.getUsername(), null);
        if(userInfo==null){
            Resp.fail("用户不存在或已注销");
        }
        Current.login(userInfo);
        return Resp.map()
                .set("isNew",isNew)
                .set("user", userInfo)
                .set("uk", user.getPassword() + TokenUtil.getGlobalSalt());
    }
    @Transactional
    protected User createUser(WxUser wxUser) {
        String uid = wxUser.getUnionId();
        if (uid == null) {
            uid = wxUser.getOpenid();
        }
        User user = new User();
        user.setCreateTime(new Date());
        user.setEnable(true);
        // user.setUsername();
        user.setUsername(uid);

        int l = uid.length();
        user.setName("用户_" + uid.substring(l - 8));
        String realPassword = PasswordUtil.generatePassword(0);
        user.setPassword(PasswordUtil.encodePassword(realPassword, user.getUsername()));
        context.publishEvent(new UserRegisterEvent(user));
        Long id = (Long) dao.save(user);
        wxUser.setUserId(id);
        dao.save(wxUser);
        return user;
    }
    protected User createUser(String phone){
        User user = new User();
        user.setCreateTime(new Date());
        user.setEnable(true);
        user.setUsername(phone);
        int l=phone.length();
        user.setName("用户_" + phone.substring(l - 4));
        String realPassword = PasswordUtil.generatePassword(0);
        user.setPassword(PasswordUtil.encodePassword(realPassword, user.getUsername()));
        context.publishEvent(new UserRegisterEvent(user));
        dao.save(user);
        return user;
    }

    @Operation(summary = "用户名密码登录")
    @PostMapping("login")
    public Resp login(@RequestBody LoginVo loginVo) {
        //时间误差30s
        if (Math.abs(System.currentTimeMillis() - loginVo.t) > 30000) {
            Resp.fail("登录超时");
        }
        String realPassword = "";
        try {
            //PlatformConfig.SystemName.strValue()
            realPassword = RsaUtil.AESDecrypt(loginVo.password, loginVo.t+"");
        } catch (Exception e) {
            Resp.fail("登录错误");
        }
        UserInfo userInfo = userService.loadUserInfo(loginVo.username, realPassword);
        if (userInfo != null) {
            Current.login(userInfo);
            return Resp.map()
                    .set("user",userInfo)
                    .set("token",userInfo.getToken())
                    .set("un", userInfo.getUserType()+userInfo.getUsername())
                    .set("uk", userInfo.getPassword() + TokenUtil.getGlobalSalt());
        } else {
            Resp.fail("用户名或密码错误");
        }
        return Resp.ok();
    }
    //验证码登录
    //公众号登录

    @Auth(login = false)
    @GetMapping(value = "/config")
    public Resp config() {
        return Resp.of(ConfigManager.getFrontConfigs());
    }
    @Schema(description = "用户登录信息")
    @Data
    public static class PhoneCodeVo {
        @Schema(description = "手机号 aes(phone,md5(t))")
        String phone;
        @Schema(description = "登录时间戳")
        long t;
    }

    /**
     * 手机验证码
     * @param phone 编码过的手机号 ase(md5(t))
     * @param t 时间戳
     * @return
     */
    @Auth(login = false)
    @PostMapping(value = "/sendPhoneCode")
    public Resp phoneCode(String phone,String t){
        if(smsService==null||t==null){
            Resp.fail("调用错误!");
        }
        if (Math.abs(System.currentTimeMillis() - Long.valueOf(t)) > 30000) {
            Resp.fail("调用超时");
        }
        try {
            String phoneNo = RsaUtil.AESDecrypt(phone, t );
            if(!Validator.isMobile(phoneNo)){
                Resp.fail("手机号错误");
            }
            String code = Captcha.phoneCode(phoneNo);
            Map<String,String> params=new HashMap<>();
            params.put("code",code);
            smsService.sendMessage(SmsConfigs.captchaSin.strValue(),phoneNo,SmsConfigs.captchaTemplate.strValue(),params);
        }catch (Exception e){
            e.printStackTrace();
            Resp.fail("调用错误");
        }
        return Resp.ok();
    }
    @Operation(summary = "手机号验证码登录")
    @PostMapping("phoneCodeLogin")
    public Resp phoneCodeLogin(String phone,String code){
        if(StringUtil.isEmpty(phone)||StringUtil.isEmpty(code)){
            Resp.fail("登录错误");
        }
        if(!Validator.isMobile(phone)||!Captcha.verifyPhoneCode(phone,code)){
            Resp.fail("验证码错误");
        }
        User user=new User();
        user.setUsername(phone);
        user=dao.loadBySql("SELECT * FROM t_user WHERE username=:username",user);
        if(user==null){
            if ("true".equals(PlatformConfig.AUTO_REG.strValue())) {
                user = createUser(phone);
            } else {
                Resp.fail("用户未注册");
            }
        }
        UserInfo userInfo = userService.loadUserInfo(user.getUsername(), null);
        if(userInfo==null){
            Resp.fail("用户不存在或已注销");
        }
        Current.login(userInfo);
        return Resp.map()
                .set("user", userInfo)
                .set("uk", user.getPassword() + TokenUtil.getGlobalSalt());
    }
}
